/***************************************************************************
 *   Copyright (C) 2007 by shinda   *
 *   shinda@babaflex   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "search.h"
#include <stdio.h>
#include <QList>
#include <string>
#include <QString>
#include <QListWidget>
#include <QListWidgetItem>
#include <QComboBox>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlResult>
#include <QSqlError>
#include <QStringList>
#include <QGroupBox>
#include <QPushButton>
#include <QLabel>
#include <QButtonGroup>
#include <QRadioButton>
#include <QLineEdit>
#include <QGridLayout>
#include <QFont>
#include <QListWidgetItem>
#include <QList>

SearchWidget::SearchWidget(QWidget *){
	QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
	db.setDatabaseName("akaal.db");
	db.open();
	qDebug() << "Is Open" << db.isOpen() << "Valid Driver" << db.isValid() ;
	qDebug() << "TABLES: " << db.tables().join(" - ");

	//Design
	fntGurmukhi = new QFont(tr("GurbaniWebThick"),14);
	searchBox = new QGroupBox;
	searchLine = new QLineEdit;
	searchResults = new QListWidget;
	//idResults = new QList;
	searchButton = new QPushButton ( tr ( "Search Now" ) );

	searchLine->setFont(*fntGurmukhi); //Sets the gurmukhi font as default
	searchResults->setFont(*fntGurmukhi);
	QButtonGroup *searchPageGroup = new QButtonGroup;
	QGroupBox *searchOptions = new QGroupBox ( tr ( "Options" ) );
	QGridLayout *searchOptionsLayout = new QGridLayout;


	searchLang = new QComboBox;
	searchLang->addItem ( tr ( "Gurmukhi" ), 0 );
	searchLang->addItem ( tr ( "English" ), 1 );

	searchType = new QComboBox;
	searchType->addItem ( tr ( "First Letters" ), 0 );
	searchType->addItem ( tr ( "All Words" ), 1 );
	searchType->addItem ( tr ( "Any Words" ), 2 );
	searchType->addItem ( tr ( "Exact Phrase" ), 3 );
	searchType->addItem ( tr ( "Main Letters (No Vowels)" ), 4 );

	searchWriters = new QComboBox;
	searchWriters->addItem ( tr ( "ALL WRITERS" ), 0 );
	searchWriters->addItem ( tr ( "ALL GURUS" ), -1 );
	searchWriters->addItem ( tr ( "ALL BHAGATS" ), -2 );
	searchWriters->addItem ( tr ( "ALL BHATTS" ), -3 );

	fillWriters(*searchWriters); // mainSearch->fillWriters());

	searchRaag = new QComboBox;
	searchRaag->addItem ( tr ( "ALL RAAGS (1-1430)" ), -1);
	fillRaags(*searchRaag);

	searchPagesAll = new QRadioButton ( tr ( "All" ) );
	searchPagesRange = new QRadioButton ( tr ( "Range" ) );
	searchPageExact = new QRadioButton ( tr ( "Exact" ) );

	//Option Labels
	searchOptionsLayout->addWidget ( new QLabel ( tr ( "Search" ) ), 0,0 );
	searchOptionsLayout->addWidget ( new QLabel ( tr ( "Languages" ) ),1,0 );
	searchOptionsLayout->addWidget ( new QLabel ( tr ( "Writers" ) ),2,0 );
	searchOptionsLayout->addWidget ( new QLabel ( tr ( "Raag" ) ),3,0 );
	searchOptionsLayout->addWidget ( new QLabel ( tr ( "Page" ) ),4,0 );

	//RadioGroup
	searchPageGroup->addButton ( searchPagesAll );
	searchPageGroup->addButton ( searchPagesRange );
	searchPageGroup->addButton ( searchPageExact );

	//Pages
	QHBoxLayout *layoutPageRange = new QHBoxLayout();
	QHBoxLayout *layoutPageExact = new QHBoxLayout();
	layoutPageRange->setAlignment( Qt::AlignLeft );
	layoutPageExact->setAlignment( Qt::AlignLeft );

	txtSearchPageStarting = new QLineEdit();
	txtSearchPageFinish = new QLineEdit();
	txtSearchPageExact = new QLineEdit();

	txtSearchPageStarting->setMaximumWidth(100);
	txtSearchPageStarting->setInputMask("00000");
	txtSearchPageFinish->setMaximumWidth(100);
	txtSearchPageFinish->setInputMask("00000");
	txtSearchPageExact->setMaximumWidth(100);
	txtSearchPageExact->setInputMask("00000");

	//Widgets
	searchOptionsLayout->addWidget ( searchType, 0, 1 );
	searchOptionsLayout->addWidget ( searchLang, 1, 1 );
	searchOptionsLayout->addWidget ( searchWriters, 2, 1 );
	searchOptionsLayout->addWidget ( searchRaag, 3, 1 );

	searchOptionsLayout->addWidget ( searchPagesAll, 4, 1 );


	layoutPageRange->addWidget( searchPagesRange, Qt::AlignLeft );
	layoutPageRange->addWidget( txtSearchPageStarting, Qt::AlignLeft );
	layoutPageRange->addWidget( txtSearchPageFinish, Qt::AlignLeft );
	layoutPageExact->addWidget( searchPageExact, Qt::AlignLeft );
	layoutPageExact->addWidget( txtSearchPageExact,1, Qt::AlignLeft );

	searchOptionsLayout->addLayout ( layoutPageRange,5, 1 );
	searchOptionsLayout->addLayout ( layoutPageExact,6, 1 );

	searchOptions->setLayout ( searchOptionsLayout );

	QLabel *searchLabel = new QLabel ( tr ( "Search: " ) );
	QGridLayout *layout = new QGridLayout;

	layout->addWidget ( searchLabel,0,0 );
	layout->addWidget ( searchLine,0,1 );
	layout->addWidget ( searchButton,1,0,1,2 );
	layout->addWidget ( searchOptions,2,0,5,2 );
	layout->addWidget ( searchResults,7,0,1,2 );

	searchBox->setLayout ( layout );
	togglePages();
	setConnections();

}

SearchWidget::~SearchWidget(){

}

void SearchWidget::fillWriters(QComboBox &cmbWriters){

//qDebug() << "Is Open" << QSqlDatabase::isOpen();
	QComboBox *lstWriters = &cmbWriters;
	//Search Writers
	QSqlQuery query( QSqlDatabase::database() );

	QStringList list;

	query.exec("SELECT * FROM Writers") ;
	qDebug() << "Last Error: "<< query.lastError().text();
	while (query.next()) {
		lstWriters->addItem( query.value(1).toString() , query.value(0).toInt() );
		//qDebug() << "result" << query.value(0).toString() << query.value(1).toString();
		list << query.value(1).toString();
	}

	//return list;
}

void SearchWidget::fillRaags(QComboBox &cmRaags){

	QComboBox *lstWriters = &cmRaags;
	//Search Writers
	QSqlQuery query( QSqlDatabase::database() );

	QStringList list;

	query.exec("SELECT RaagID, RaagWithPage FROM Raag") ;
	qDebug() << "Last Error: "<< query.lastError().text();
	while (query.next()) {
		lstWriters->addItem( query.value(1).toString() , query.value(0).toInt() );
		//qDebug() << "result" << query.value(0).toString() << query.value(1).toString();
		list << query.value(1).toString();
	}

	//return list;
}

void SearchWidget::performSearch(){

	searchResults->clear();	 //Clear List
	idResults.clear();

	//Get list of Shabad Items
	QSqlQuery query( QSqlDatabase::database() );


	qDebug() << getSQLStatement();
	query.exec(getSQLStatement()) ;
	qDebug() << "Last Error: "<< query.lastError().text();
	while (query.next()) {
		idResults.append(query.value(0).toInt());
		searchResults->addItem( query.value(2).toString() ); //Add results to list.
	}


}

QString SearchWidget::getSQLStatement(){
	//First part of the sQL Statement will always be the same.
	QString sqlCommand = "SELECT * FROM Shabad WHERE ";
	QStringList wordsList;

	//Check Languages
	if ( searchLang->currentIndex()  == 0){ //Gurmukhi

		//Check What is being searched (letters vs phrase)
		switch ( searchType->currentIndex() ){ //searchType->currentIndex
		//0 - First Letters, 1 - All Words 2 - Any Words 3 - Exact Phrase, 4 - MainLetters
		case 0:	//First Letters
			sqlCommand = sqlCommand + " firstLetterStr LIKE '%" + String2Ascii( searchLine->text() ) + "%' " ;
			break;
		case 1:
			//Loop Over Words in search split string by space.
			wordsList = searchLine->text().split(" ");
			for (int x = 0; x < wordsList.count()-1; x++)  {
				sqlCommand.append(" (gurmukhi LIKE '%");
				sqlCommand.append(wordsList.takeFirst());
				sqlCommand.append("%') AND ");
			}
			sqlCommand.append(" (gurmukhi LIKE '%");
			sqlCommand.append(wordsList.takeFirst());
			sqlCommand.append("%') ");
			break;
		case 2: //TODO Seperate Words
			//Loop Over Words in search split string by space.
			wordsList = searchLine->text().split(" ");
			for (int x = 0; x < wordsList.count()-1; x++)  {
				sqlCommand.append(" (gurmukhi LIKE '%");
				sqlCommand.append(wordsList.takeFirst());
				sqlCommand.append("%') || ");
			}

			sqlCommand.append(" (gurmukhi LIKE '%");
			sqlCommand.append(wordsList.takeFirst());
			sqlCommand.append("%') ");
			break;
		case 3: //Exact Phrase
			sqlCommand.append(" gurmukhi LIKE '%");
			sqlCommand.append(searchLine->text());
			sqlCommand.append("%' ");
			break;
		case 4: //TODO Filter Main Letters
			sqlCommand.append(" MainLetters = '% ");
			sqlCommand.append( searchLine->text() );
			sqlCommand.append("%'");
			break;
		}
	}
	else if (searchLang -> currentIndex() == 1){ //English
		//TODO Insert switc statement to allow english to have options of exact phrase, partial phrase, all words
		sqlCommand += " english LIKE '%" + searchLine->text() + "%' ";
	}

	//Check Writers

	//TODO	Allow for multiple writers
	switch ( searchWriters->itemData(searchWriters->currentIndex()).toInt() ) {
		case -1: //All Guru's
			sqlCommand += " AND (WriterID > 0) AND (WriterID < 7)";
			break;
		case -2: //All Bhagats
			sqlCommand += " AND (WriterID > 6) AND (WriterID < 22)";
			break;
		case -3: //All Bhaats
			sqlCommand += " AND (WriterID > 29)";
			break;
		case 0:
			break;
		default:
			sqlCommand += " AND (WriterID =" + searchWriters->itemData( searchWriters->currentIndex() ).toString() + ") ";
			break;
	}

	//Check Raag
	//TODO Allow for multiple Raags
	if (searchRaag->itemData(searchRaag->currentIndex()).toInt() > -1)
		sqlCommand += " AND (RaagID = " + searchRaag->itemData(searchRaag->currentIndex()).toString() + ")";

	if ( searchPageExact->isChecked() )
		sqlCommand += "AND (PageNo = " + txtSearchPageExact->text() + ")";
	else if (searchPagesRange->isChecked() ){
		sqlCommand += "AND (PageNo > ";

		if ( txtSearchPageStarting->text().toInt() < txtSearchPageFinish->text().toInt() )
			sqlCommand += txtSearchPageStarting->text();
		else
			sqlCommand += txtSearchPageFinish->text();
		sqlCommand += ") AND (PageNo <";

		if ( txtSearchPageStarting->text().toInt() < txtSearchPageFinish->text().toInt() )
			sqlCommand += txtSearchPageFinish->text();
		else
			sqlCommand += txtSearchPageStarting->text();

		sqlCommand += ")";
	}
	sqlCommand += "ORDER BY Shabad.ShabadID ASC, Shabad.Line_No ASC LIMIT 50"; //Limit Number of retrieved.
	return sqlCommand;
}

QString SearchWidget::String2Ascii(const QString &str){
	QString temp = ""; //temporary string

	/*
	Get Total characters of String and loop over each character and convert to ascii
	*/
	QByteArray asciiArray =	str.toAscii();
	printf("Ascii -> %d\n", asciiArray.length() );

	//temp.append( asciiArray.length() );
	bool k;
	for (int x = 0; x < asciiArray.length(); x++){
		temp +=  QString::number( (int)asciiArray[x] )+ ",";
	}

	return temp;


}

void SearchWidget::togglePages(){
	//if Ranges is selected
	if (searchPagesRange->isChecked()){
		txtSearchPageStarting->setEnabled( true );
		txtSearchPageFinish->setEnabled( true );
		txtSearchPageExact->setEnabled( false );
	}
	else if ( searchPageExact->isChecked() ){
		txtSearchPageExact->setEnabled( true );
		txtSearchPageStarting->setEnabled( false );
		txtSearchPageFinish->setEnabled( false );
	}
	else{
		txtSearchPageStarting->setEnabled( false );
		txtSearchPageFinish->setEnabled( false );
		txtSearchPageExact->setEnabled( false );
	}
}

void SearchWidget::sendShabad(){
	//Get corresponding id's of items from second list.
	qDebug() << "Item Selected1 -> " <<  idResults.at(searchResults->currentRow());
	emit shabadSelect(idResults.at(searchResults->currentRow()));
	//emit shabadSelect(5);
}

void SearchWidget::setConnections(){
	connect (searchButton, SIGNAL ( clicked() ), this, SLOT ( performSearch() ) );
	connect (searchPageExact, SIGNAL ( toggled(bool) ), this, SLOT ( togglePages() ) );
	connect (searchPagesRange, SIGNAL ( toggled( bool ) ), this, SLOT ( togglePages() ) );
	connect (searchPagesAll, SIGNAL ( toggled( bool ) ), this, SLOT ( togglePages() ) );
	connect (searchResults, SIGNAL ( itemDoubleClicked( QListWidgetItem *)), this, SLOT (sendShabad()));
}